/*!
 *  \file       InputSignal.cpp
 *  \brief      Implementazione della classe \c InputSignal
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author	Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 *
 */

#include <vector>
#include <algorithm>
#include <functional>
#include "ISignalNoise.hpp"
#include "ISignalGenerator.hpp"
#include "InputSignal.hpp"

using namespace std;


/*!
 *  \brief	Costruttore della classe \c InputSignal
 *
 *  \param[in]	numPoints	numero di punti da campionare
 *  \param[in]	generator	generatore di segnale da utilizzare
 *
 *  \see	InputSignal< tType >::InputSignal( InputSignal< tType > const& other )
 */
template< class tType >
InputSignal< tType >::InputSignal( const unsigned long int numPoints, ISignalGenerator< tType > & generator )
    : vector< tType >( numPoints )
{
  // this is equivalent to generate( this->begin( ), this->end( ), generator )
  // but it doesn't works cuz doesn't want a reference
  for( typename InputSignal< tType >::iterator first = this->begin( ); first != this->end( ); ++first )
    *first = generator();
}

/*!
 *  \brief      Costruttore di copia della classe \c InputSignal
 *  \param[in]	other	segnale da copiare
 *
 *  \see	InputSignal< tType >::InputSignal( const unsigned long int numPoints, ISignalGenerator< tType > const& generator )
 */
template< class tType >
InputSignal< tType >::InputSignal( InputSignal< tType > const& other )
    : vector< tType >( static_cast< vector< tType > >( other ) )
{
}


/*!
 *  \brief      Operatore di assegnazione della classe \c InputSignal
 */
template < typename tType > InputSignal< tType >&
InputSignal< tType >::operator=( const InputSignal< tType >& other )
{
   if (this == &other) {
       return *this;
   }
   
   this->resize( (&other)->size( ) );
   
   for( unsigned long int i = 0; i < this->size(); ++i )
     (*this)[i] = other[i];
   
   return *this;
}


/*!
 *  \brief      Numero delle componenti diverse da 0
 *  \return	ritorna il numero delle componenti del segnale diverse da 0
 */
template< class tType > int
InputSignal< tType >::nonZeroElements( void ) const
{
  return count_if( this->begin(), this->end(), bind2nd( greater< tType >( ), tType( 0 ) ) ); 
}

/*!
 *  \brief      Ritorna il valore massimo del segnale
 */
template< class tType > tType
InputSignal< tType >::getMax( void )
{
  return tType( *max_element( this->begin(), this->end() ) );
}

/*!
 *  \brief      Ritorna il valore minimo del segnale
 */
template< class tType > tType
InputSignal< tType >::getMin( void )
{
  return tType( *min_element( this->begin(), this->end() ) );
}

/*!
 *  \brief      Ritorna l'indice del valore massimo
 */
template< class tType > unsigned long int
InputSignal< tType >::indexOfMax( void )
{
  return distance( this->begin(), max_element( this->begin(), this->end() ) );
}

/*!
 *  \brief      Ritorna l'indice del valore minimo
 */
template< class tType > unsigned long int
InputSignal< tType >::indexOfMin( void )
{
  return distance( this->begin(), min_element( this->begin(), this->end() ) );
}

/*!
 *  \brief      Applica il rumore dato al segnale
 */
template< class tType > void
InputSignal< tType >::addNoise( ISignalNoise< tType > &noise )
{
  // this is equivalent to transform( this->begin( ), this->end( ), this->begin( ), noise )
  // but it doesn't works cuz doesn't want a reference
  for( typename InputSignal< tType >::iterator first = this->begin( ); first != this->end( ); ++first )
    *first = noise( *first );
}
